package com.xjtu.common.weblog;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 统一日志处理切面
 * Created by 石磊
 */
@Aspect
@Component
@Slf4j
@Order(1)
public class WebLogAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);

    //切入点排除WSController
    @Pointcut("execution(public * com.xjtu.controller..*.*(..)) && " +
            "!execution(public * com.xjtu.controller.WebSocketController.*(..)) &&"+
            "!execution(public * com.xjtu.controller.WSController.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
    }

    @AfterReturning(value = "webLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {
    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //把startTime 转换为String类型
        Long startTimeDate = System.currentTimeMillis();
        String startTime = DateUtil.now();

        //获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //记录请求信息(通过Logstash传入Elasticsearch)
        WebLog webLog = new WebLog();
        webLog.setStartTime(startTime);

        Object result = joinPoint.proceed();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation log = method.getAnnotation(ApiOperation.class);
            webLog.setDescription(log.value());
        }

//        String urlStr = request.getRequestURL().toString();
//        webLog.setIp(request.getRemoteUser());
//        LOGGER.error("ip:{}", webLog.getIp());

//        webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));

        //获取相对路径
        webLog.setUri(request.getRequestURI());
        //判断请求方式
        webLog.setMethod(request.getMethod());
        //获取请求参数
        if ("GET".equals(request.getMethod())) {
//            webLog.setParameter(request.getQueryString());
            Map<String, String[]> parameterMap = request.getParameterMap();
            Map<String, Object> paramMap = new HashMap<>();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                paramMap.put(entry.getKey(), entry.getValue()[0]);
            }
            webLog.setParameter(paramMap);
        } else {
            Object[] args = joinPoint.getArgs();
            //将args转换为map对象
            Map<String, Object> paramMap = new HashMap<>();
            boolean flag = false;// 看是否有文件上传
            for (Object arg : args) {

                if (arg instanceof MultipartFile) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                for (Object arg : args) {
                    paramMap.putAll(JSONObject.parseObject(JSON.toJSONString(arg), Map.class));
                }
                webLog.setParameter(paramMap.toString());
            } else {
                paramMap.put("file", "文件上传");
                paramMap.put("文件链接", JSONObject.parseObject(JSON.toJSONString(result), Map.class).get("data"));
                webLog.setParameter(paramMap.toString());
            }
        }
        Long endTimeDate = System.currentTimeMillis();
        webLog.setSpendTime((int) (endTimeDate - startTimeDate) + "ms");

        //将webLog转换为map对象
        Map<String, Object> webLogMap = JSONObject.parseObject(JSON.toJSONString(webLog), Map.class);


//        cn.hutool.json.JSON json= JSONUtil.parse(webLog);

        //获取当前的月份时间
        String month = DateUtil.format(new Date(), "yyyy-MM");
        //获取当前的月份和天数
        String day = DateUtil.format(new Date(), "MM-dd");
        //判断文件夹是否存在，不存在则创建
        String monthPath = "./log/" + month;
        File dir = new File(monthPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String dayPath = monthPath + "/" + day + ".log";
        //判断文件operation.log是否存在,不存在则创建
        File file = new File(dayPath);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //将json信息写入文件
        FileUtil.appendUtf8String(webLogMap.toString() + "\n", file);

        return result;
    }
}